package com.itlong.cloud.intercept;


import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.utils.encrypt.DesEncryptUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <desc>
 *      请求入参和返回拦截器
 * </desc>
 *
 * @createDate 2019/09/17
 */
@Aspect
@Component
@Order(0)
public class AppParamIntercept {

    private static Logger LOG = LoggerFactory.getLogger(AppParamIntercept.class);

    @Value("${" + PlatformConstants.APP_REQUEST_PARAMS_ENCRYPT_KEY + "}")
    public String APP_REQUEST_PARAMS_ENCRYPT_KEY;

    @Value("${" + PlatformConstants.APP_USER_TOKEN_KEY + "}")
    public String APP_USER_TOKEN_KEY;

    //拦截点
    @Pointcut("(execution(* com.itlong.cloud.controller.current..*.*(..)) || execution(* com.itlong.cloud.controller.pad.AppFaceRecognitionController.*(..))) && !@annotation(com.itlong.cloud.annotation.UnParamEncrypt)")
    public void executeService(){}

    /**
     * <desc>
     *      请求入参和返回拦截器方法
     * </desc>
     *
     * @author wangzhi
     * @createDate 2019/09/17
     */
    @Around("executeService()")
    public Object handleParam(ProceedingJoinPoint thisJoinPoint) throws Throwable{
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String requestUrl = request.getRequestURL().toString();
        //入参密文
        String encryptScript = request.getParameter("ciphertext");
        if (StringUtils.isBlank(encryptScript)) {
            //加密串未携带，目前不算参数异常，为兼容此版本之前的app版本
            return thisJoinPoint.proceed();
        } else {
            //解密入参
//                String encryptResult = DesEncryptUtil.aesDecryptApp(encryptScript, "5278MMN5412365UH");
            String encryptResult = UserTokenUtil.getPassword(encryptScript, APP_USER_TOKEN_KEY);
            if (StringUtils.isBlank(encryptResult)) {
                // 因ios上传图片时字符串过长，加密只能分段加密，这边一次解密会有乱码存在，图片无法解码，故ios上传图片时部分加密再拼接原文，这边截取之后解密部分加密部分再连接原字符串
                String[] encryptScriptArr = encryptScript.split("5278MMN5412365UH");
                encryptResult = UserTokenUtil.getPassword(encryptScriptArr[0], APP_USER_TOKEN_KEY);
                if (StringUtils.isBlank(encryptResult)) {
                    return getEncryptResult(new MessageVO(BaseErrorCodeEnum.PARAM_ERR.getErrorCode()));
                }
                encryptResult = encryptResult + encryptScriptArr[1];
            }
            encryptResult = encryptResult.trim();
            encryptResult = encryptResult.replaceAll("&quot;","\"");
//                encryptResult = URLDecoder.decode(encryptResult, "UTF-8");
            //验签，app验签在接口方法里面，这边先去掉验签
            JSONObject jsStr = JSONObject.parseObject(encryptResult);//入参转json
            Map<String, Object> params;//入参转map
            params = JsonUtil.toObject(encryptResult, HashMap.class);
            // 将参数放入请求域中
            HttpProtocolUtil.setRequestAttributes(params, request);

            Object result = thisJoinPoint.proceed();

            //签名且加密
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
            Date date = new Date();
            String createTime = df.format(date);
            String resultJson = JsonUtil.toJSON(result);
            JSONObject json = new JSONObject();
            Map<String, Object> jsonToMap = new HashMap<>();
            jsonToMap.put("data", resultJson);
            String sign = Md5EncryptUtil.cloudDeviceMd5(jsonToMap, createTime, APP_REQUEST_PARAMS_ENCRYPT_KEY);
            json.put("allData", resultJson);
            json.put("createTime", createTime);
            json.put("sign", sign);
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("ciphertext", Base64.encode(DesEncryptUtil.Encrypt(URLEncoder.encode(new String(json.toJSONString().getBytes()), "utf-8").getBytes(), APP_USER_TOKEN_KEY)));

            return resultMap;
        }
    }

    /**
     * <desc>
     *      返回加密内容
     * </desc>
     *
     * @author wangzhi
     * @createDate 2019/09/17
     */
    private Map<String, Object> getEncryptResult(Object result) throws Exception {
        JSONObject json = new JSONObject();
        Date date = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        String createTime = df.format(date);
        Map<String, Object> jsonToMap = new HashMap<>();
        jsonToMap.put("data", JsonUtil.toJSON(result));
        String sign = Md5EncryptUtil.cloudDeviceMd5(jsonToMap, createTime, APP_REQUEST_PARAMS_ENCRYPT_KEY);
        json.put("allData", JsonUtil.toJSON(result));
        json.put("createTime", createTime);
        json.put("sign", sign);
        String encryptResult = Base64.encode(DesEncryptUtil.Encrypt(URLEncoder.encode(new String(json.toJSONString().getBytes()), "utf-8").getBytes(), APP_USER_TOKEN_KEY));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("ciphertext", encryptResult);
        return resultMap;
    }

}
